import type { AxiosProgressEvent } from 'axios'
import { uploadFileChunkApi, mergeFileChunksApi } from '@/api/file/fileUpload'

// 生成稳定的上传ID（基于文件名/大小/修改时间），用于后端识别同一文件的分片会话
export async function generateUploadId(file: File) {
  try {
    const input = `${file.name}:${file.size}:${file.lastModified}`
    const data = new TextEncoder().encode(input)
    const hash = await crypto.subtle.digest('SHA-256', data)
    return Array.from(new Uint8Array(hash)).map(b => b.toString(16).padStart(2, '0')).join('')
  } catch {
    return `${file.name}-${file.size}-${file.lastModified}`
  }
}

export type UploadInChunksOptions = {
  chunkSize?: number
  // 进度通知：0-100
  onProgress?: (pct: number) => void
  // 分片编号基准（有的后端从 0 开始，有的从 1 开始）；默认 0-based
  indexBase?: 0 | 1
  // 每片失败后的最大重试次数
  maxRetriesPerChunk?: number
  // 业务模块标识：传给后端区分业务场景
  module?: string
}

// 通用分片上传（固定使用内置 API，不再支持自定义 sendChunk / mergeChunks）
export async function uploadInChunks(file: File, opts: UploadInChunksOptions) {
    // console.log('上传文件3:', file)
  const chunkSize = Math.max(256 * 1024, opts.chunkSize ?? 2 * 1024 * 1024)
  if (!file || !file.size) throw new Error('无效的文件')
  const totalChunks = Math.max(1, Math.ceil(file.size / chunkSize))
  const baseId = await generateUploadId(file)
  // 附加一次性随机后缀，避免服务端历史分片冲突
  const uniqueSuffix = `${Date.now().toString(36)}${Math.random().toString(36).slice(2, 6)}`
  const fileId = `${baseId}-${uniqueSuffix}`
  const idxBase = opts.indexBase ?? 0
  const maxRetries = Math.max(0, opts.maxRetriesPerChunk ?? 2)

  // 固定内置实现
  const sendChunk = async ({ fileId, chunkIndex, chunk }: { fileId: string; chunkIndex: number; chunk: Blob }, onProgress?: (evt: AxiosProgressEvent) => void) => {
    
    // console.log('上传文件4:', fileId, chunkIndex, chunk)
    return uploadFileChunkApi({ module: opts.module || 'default', fileId, chunkIndex, chunk }, onProgress)
  }
  const mergeAll = async ({ fileId, totalChunks, fileName }: { fileId: string; totalChunks: number; fileName: string }) => {
    return mergeFileChunksApi({ module: opts.module || 'default', fileId, totalChunks, fileName })
  }

  let uploadedBytes = 0
  for (let index = 0; index < totalChunks; index++) {
    const start = index * chunkSize
    const end = Math.min(file.size, start + chunkSize)
  // 带上原始类型，避免切片后 MIME 为空导致后端拒绝
  const blob = file.slice(start, end, file.type || undefined)

    let lastErr: any = null
    let success = false
    for (let attempt = 1; attempt <= (1 + maxRetries); attempt++) {
      try {
        // console.log('上传文件4:', fileId, index + idxBase, blob)
        const resp = await sendChunk(
          { fileId, chunkIndex: index + idxBase, chunk: blob },
          (evt) => {
            if (opts.onProgress) {
              const loaded = evt.loaded ?? 0
              const total = file.size
              const pct = Math.min(99, Math.round(((uploadedBytes + loaded) / total) * 100))
              opts.onProgress(pct)
            }
          },
        )
        const ok = (resp as any)?.success === true || (resp as any)?.code === 0 || (resp as any)?.code === 200
        if (ok) { success = true; break }
        lastErr = (resp as any)?.message || '分片上传返回异常'
      } catch (err: any) {
        lastErr = err
      }
      if (attempt <= maxRetries) await new Promise(r => setTimeout(r, 300 * attempt))
    }
    if (!success) throw new Error(typeof lastErr === 'string' ? lastErr : (lastErr?.message || '上传分片失败'))
    uploadedBytes += blob.size
  }
  console.log('上传文件5: 合并分片', fileId, totalChunks, file.name)
  const mergeRes = await mergeAll({ fileId, totalChunks, fileName: file.name })
  const ok = (mergeRes as any)?.success === true || (mergeRes as any)?.code === 0 || (mergeRes as any)?.code === 200
  if (!ok) throw new Error((mergeRes as any)?.message || '合并失败')
  if (opts.onProgress) opts.onProgress(100)
  return { fileId, totalChunks, response: mergeRes }
}

// 便捷方法：直接使用内置 API（语义更明确）
export async function uploadFileInChunksDirect(file: File, options?: UploadInChunksOptions) {
  return uploadInChunks(file, { ...(options || {}) })
}
